# retry_decorators.py
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type, before_sleep_log, after_log
import logging
from loguru import logger

from functools import wraps
from datetime import datetime

import time
import threading  # 添加线程模块


# 装饰器配置类
class DecoratorConfig:
    def __init__(self):
        self.performance_monitoring_enabled = True
        self.debug_logging_enabled = True
        self.call_time_logging_enabled = True
        self.thread_time_analysis_enabled = True  # 新增线程时间分析开关

# 全局配置实例
decorator_config = DecoratorConfig()

def set_decorator_config(**kwargs):
    """设置装饰器配置"""
    for key, value in kwargs.items():
        if hasattr(decorator_config, key):
            setattr(decorator_config, key, value)
            logger.info(f"装饰器配置 {key} 已设置为 {value}")

# 定义简单的日志记录函数，使用 loguru
def log_retry_attempt(retry_state):
    """记录重试尝试"""
    logger.warning(f"重试函数 {retry_state.fn.__name__}，原因: {retry_state.outcome.exception()}，"
                  f"等待时间: {getattr(retry_state.next_action, 'sleep', 0):.2f}秒")

def log_retry_final(retry_state):
    """记录最终重试结果"""
    logger.error(f"函数 {retry_state.fn.__name__} 最终失败，经过 {retry_state.attempt_number} 次尝试，"
                f"最终错误: {retry_state.outcome.exception()}")

# 定义常见的重试策略装饰器
# 等待的事件单位是s 超时等待
def retry_can_operation(max_attempts=3, min_wait=0.1, max_wait=0.5):
    """
    用于 CAN 操作的重试装饰器 - 指数退避
    """
    def decorator(func):
        return retry(
            stop=stop_after_attempt(max_attempts),
            wait=wait_exponential(multiplier=1, min=min_wait, max=max_wait),
            retry=retry_if_exception_type((Exception,)),
            before_sleep=log_retry_attempt,
            after=log_retry_final,
            reraise=True
        )(func)
    return decorator

def retry_network_operation(max_attempts=5, min_wait=2, max_wait=20):
    """
    用于网络操作的重试装饰器 - 指数退避
    """
    def decorator(func):
        return retry(
            stop=stop_after_attempt(max_attempts),
            wait=wait_exponential(multiplier=1, min=min_wait, max=max_wait),
            retry=retry_if_exception_type((ConnectionError, TimeoutError)),
            before_sleep=log_retry_attempt,
            after=log_retry_final,
            reraise=True
        )(func)
    return decorator

def retry_file_operation(max_attempts=3, min_wait=1, max_wait=5):
    """
    用于文件操作的重试装饰器 - 指数退避
    """
    def decorator(func):
        return retry(
            stop=stop_after_attempt(max_attempts),
            wait=wait_exponential(multiplier=1, min=min_wait, max=max_wait),
            retry=retry_if_exception_type((IOError, OSError)),
            before_sleep=log_retry_attempt,
            after=log_retry_final,
            reraise=True
        )(func)
    return decorator

# 预定义的装饰器实例，可以直接使用
retry_can = retry_can_operation()
retry_network = retry_network_operation()
retry_file = retry_file_operation()


# 可配置的时间记录装饰器
def log_call_time(logger=None):
    """
    记录函数调用时间的装饰器
    
    参数:
    logger: 日志记录器实例，如果未提供则使用默认的日志记录器
    """
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            if decorator_config.call_time_logging_enabled:
                call_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
                if logger:
                    logger.debug(f"调用函数 {func.__name__} 的时间: {call_time}")
                else:
                    # 使用默认的日志记录器
                    logging.getLogger().debug(f"调用函数 {func.__name__} 的时间: {call_time}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

# 可配置的性能分析装饰器
def timing_analysis(func):
    """
    可配置的性能分析装饰器
    """
    @wraps(func)
    def wrapper(*args, **kwargs):
        if decorator_config.performance_monitoring_enabled:
            start_time = time.perf_counter()
            try:
                result = func(*args, **kwargs)
                return result
            finally:
                end_time = time.perf_counter()
                elapsed_time = end_time - start_time
                logger.debug(f"[性能] {func.__name__} 执行时间: {elapsed_time*1000:.2f} ms")
        else:
            # 装饰器禁用时直接执行函数
            return func(*args, **kwargs)
    return wrapper

# 创建可配置的循环性能分析装饰器
def create_loop_timing_decorator(interval=100, threshold=50):
    """
    创建可配置的循环性能分析装饰器
    
    参数:
    interval: 每隔多少次循环记录一次日志
    threshold: 时间阈值(ms)，超过此时间也会输出日志
    """
    def loop_timing_decorator(func):
        func._loop_count = 0
        
        @wraps(func)
        def wrapper(*args, **kwargs):
            if decorator_config.performance_monitoring_enabled:
                func._loop_count += 1
                start_time = time.perf_counter()
                
                try:
                    result = func(*args, **kwargs)
                    return result
                finally:
                    end_time = time.perf_counter()
                    elapsed_time = end_time - start_time
                    
                    # 每隔 interval 次记录一次，或者当时间超过阈值时记录
                    if func._loop_count % interval == 0 or elapsed_time > threshold/1000:
                        logger.info(f"[循环性能] {func.__name__} 第{func._loop_count}次循环: {elapsed_time*1000:.2f} ms")
            else:
                return func(*args, **kwargs)
        return wrapper
    return loop_timing_decorator

# 预定义的循环性能分析装饰器实例
loop_timing_analysis = create_loop_timing_decorator()

# 新增的基础线程时间分析装饰器
def thread_time_analysis(func):
    """
    基础线程时间分析装饰器 - 可配置
    
    记录函数执行的墙钟时间和CPU时间，帮助分析线程时间片使用情况
    """
    @wraps(func)
    def wrapper(*args, **kwargs):
        # 检查是否启用线程时间分析
        if decorator_config.thread_time_analysis_enabled:
            # 获取当前线程信息
            current_thread = threading.current_thread()
            thread_name = current_thread.name
            thread_id = current_thread.ident
            
            # 记录开始时间
            start_time = time.perf_counter()
            # 尝试获取线程CPU时间（Python 3.7+支持）
            start_thread_time = time.thread_time() if hasattr(time, 'thread_time') else time.process_time()
            
            try:
                # 执行原函数
                result = func(*args, **kwargs)
                return result
            finally:
                # 记录结束时间
                end_time = time.perf_counter()
                end_thread_time = time.thread_time() if hasattr(time, 'thread_time') else time.process_time()
                
                # 计算执行时间
                wall_time = end_time - start_time
                cpu_time = end_thread_time - start_thread_time
                
                # 记录日志 - 包含线程信息和时间分析
                logger.debug(f"[线程时间分析] {func.__name__} "
                            f"线程: {thread_name}({thread_id}) "
                            f"总耗时: {wall_time*1000:.2f}ms "
                            f"CPU时间: {cpu_time*1000:.2f}ms "
                            f"时间片利用率: {cpu_time/wall_time*100:.1f}%"
                            if wall_time > 0 else "N/A")
        else:
            # 装饰器禁用时直接执行函数
            return func(*args, **kwargs)
    return wrapper

# 更新 __all__ 列表，确保新装饰器可以被正确导入
__all__ = [
    'retry_can', 'retry_network', 'retry_file',
    'timing_analysis', 'log_call_time',
    'loop_timing_analysis', 'thread_time_analysis',  # 添加新的装饰器
    'set_decorator_config'
]